package com.example.feidaolumanager.pages.ui.map

import android.Manifest
import android.app.AlertDialog
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.location.Location
import android.location.LocationManager
import android.os.Build
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.RequiresApi
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.viewinterop.AndroidView
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat.getSystemService
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewmodel.compose.viewModel
import com.amap.api.location.AMapLocation
import com.amap.api.location.AMapLocationClient
import com.amap.api.location.AMapLocationClientOption
import com.amap.api.location.AMapLocationListener
import com.amap.api.maps.AMap
import com.amap.api.maps.AMapUtils
import com.amap.api.maps.MapView
import com.amap.api.maps.MapsInitializer
import com.amap.api.maps.model.BitmapDescriptorFactory
import com.amap.api.maps.model.LatLng
import com.amap.api.maps.model.Marker
import com.amap.api.maps.model.MarkerOptions
import com.amap.api.maps.model.RoutePara
import com.example.feidaolu.base.LoadState
import com.example.feidaolumanager.Constants
import com.example.feidaolumanager.LoginActivity
import com.example.feidaolumanager.adapter.MyMarkerInfoWindowAdapter
import com.example.feidaolumanager.componant.DropdownSelectLevel3Area
import com.example.feidaolumanager.databinding.FragmentMapBinding
import com.example.feidaolumanager.pojo.User
import com.example.feidaolumanager.viewModel.SettingViewModel


class MapFragment : Fragment() {

    private var _binding: FragmentMapBinding? = null

    // This property is only valid between onCreateView and
    // onDestroyView.
    private val binding get() = _binding!!


    private lateinit var user: User

    // 记录通过高德获取的当前位置
    private lateinit var mAMapLocation: AMapLocation

    private var mMapView: MapView? = null


    // 创建一个二维数据存放重复的点
    private var markersWithSamePos: ArrayList<ArrayList<Marker>> = arrayListOf()

    private lateinit var registerForActivityResult: ActivityResultLauncher<Array<String>>

    @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
    ): View {
        registerForActivityResult = registerForActivityResult(
            ActivityResultContracts
                .RequestMultiplePermissions()
        ) { map ->
            if (map.values.all { it }) {
                Toast.makeText(context, "获取权限成功", Toast.LENGTH_LONG)
                    .show()
            } else {
                Toast.makeText(
                    context, "获取位置失败,没有相应的权限", Toast.LENGTH_LONG
                ).show()
            }
        }
        _binding = FragmentMapBinding.inflate(inflater, container, false)
        val root: View = binding.root

        val mapViewModel: MapViewModel by lazy {
            ViewModelProvider(this)[MapViewModel::class.java]
        }


        val myMarkerInfoWindowAdapter = MyMarkerInfoWindowAdapter(requireContext())

        MapsInitializer.updatePrivacyShow(context, true, true)
        MapsInitializer.updatePrivacyAgree(context, true)


        //获取地图控件引用
        //在activity执行onCreate时执行mMapView.onCreate(savedInstanceState)，创建地图


        user = activity?.intent?.getSerializableExtra("user") as User


//        mapViewModel.getMachineInfos(user.token, user.ss_id, null, null)
        // 调用后台接口获取所有的工地数据

        // 设置点击地图上添加的点的时候，显示的弹窗内容


        val locationPermissionRequest = registerForActivityResult(
            ActivityResultContracts.RequestMultiplePermissions()
        ) { permissions ->
            when {
                permissions.getOrDefault(Manifest.permission.ACCESS_FINE_LOCATION, false) -> {
                    // Precise location access granted.
                }

                permissions.getOrDefault(Manifest.permission.ACCESS_COARSE_LOCATION, false) -> {
                    // Only approximate location access granted.
                }

                else -> {
                    // No location access granted.
                }
            }
        }

// ...

// Before you perform the actual permission request, check whether your app
// already has the permissions, and whether your app needs to show a permission
// rationale dialog. For more details, see Request permissions.
        locationPermissionRequest.launch(
            arrayOf(
                Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION
            )
        )

        val locationManager = context?.let { getSystemService(it, LocationManager::class.java) }

        // 看不懂，但必须要的权限检测
        if (context?.let {
                ActivityCompat.checkSelfPermission(
                    it, Manifest.permission.ACCESS_FINE_LOCATION
                )
            } != PackageManager.PERMISSION_GRANTED && context?.let {
                ActivityCompat.checkSelfPermission(
                    it, Manifest.permission.ACCESS_COARSE_LOCATION
                )
            } != PackageManager.PERMISSION_GRANTED) {
            println("context异常的为空")
        }

        //声明AMapLocationClient类对象
        //声明AMapLocationClient类对象
        val mLocationClient: AMapLocationClient?
        //声明定位回调监听器
        //声明定位回调监听器
        val mLocationListener = AMapLocationListener { amapLocation ->
            // 首先，可以判断AMapLocation对象不为空，当定位错误码类型为0时定位成功。
            if (amapLocation != null) {
                if (amapLocation.errorCode == 0) {
                    //可在其中解析amapLocation获取相应内容。
                    mAMapLocation = amapLocation
                } else {
                    //定位失败时，可通过ErrCode（错误码）信息来确定失败的原因，errInfo是错误信息，详见错误码表。
                    Log.e(
                        "AmapError",
                        "location Error, ErrCode:" + amapLocation.getErrorCode() + ", errInfo:" + amapLocation.getErrorInfo()
                    )
                }
            }
        }
        //初始化定位
        //初始化定位
        mLocationClient = AMapLocationClient(context)
        //设置定位回调监听
        //设置定位回调监听
        mLocationClient.setLocationListener(mLocationListener)


        //声明AMapLocationClientOption对象
        //声明AMapLocationClientOption对象
        val mLocationOption: AMapLocationClientOption?
//初始化AMapLocationClientOption对象
//初始化AMapLocationClientOption对象
        mLocationOption = AMapLocationClientOption()

        /**
         * 设置定位场景，目前支持三种场景（签到、出行、运动，默认无场景）
         */
        mLocationOption.setLocationPurpose(AMapLocationClientOption.AMapLocationPurpose.SignIn)


        //给定位客户端对象设置定位参数
        mLocationClient.setLocationOption(mLocationOption)
        //启动定位
        mLocationClient.startLocation()


        // template
        binding.tvCompose.setContent {
            Page(
                mapViewModel, savedInstanceState, myMarkerInfoWindowAdapter, locationManager
            )

        }


        // 一开始显示所有的点
        mapViewModel.getMachineInfos(user)

        return root
    }

    @Composable
    @OptIn(ExperimentalMaterial3Api::class)
    private fun Page(
        mapViewModel: MapViewModel,
        savedInstanceState: Bundle?,
        myMarkerInfoWindowAdapter: MyMarkerInfoWindowAdapter,
        locationManager: LocationManager?,
        settingViewModel: SettingViewModel = viewModel(factory = SettingViewModel.Factory)
    ) {

        settingViewModel.isShowNavigationDialog.collectAsState()

        Scaffold(topBar = {
            TopAppBar(
                title = {
                    Text("地图", color = Color.White)
                },
                modifier = Modifier.background(color = Color.DarkGray),
                colors = TopAppBarDefaults.smallTopAppBarColors(containerColor = Color(0, 172, 98))
            )
        }) { paddingValues ->
            Column(modifier = Modifier.padding(paddingValues)) {
                DropdownSelectLevel3Area(user = user, onSelected = {
                    mapViewModel.getMachineInfos(user, it, 3)
                })

                AndroidView(factory = {
                    val mapView = MapView(this@MapFragment.activity)
                    mapView.onCreate(savedInstanceState)
                    mMapView = mapView
                    mapView
                }) { mapView ->

                    val aMap = mapView.map

                    Log.e(this@MapFragment.toString(), "onCreateView: 创建地图一次")
                    aMap?.isTrafficEnabled = false // 显示实时交通状况


                    //地图模式可选类型：MAP_TYPE_NORMAL,MAP_TYPE_SATELLITE,MAP_TYPE_NIGHT
                    //地图模式可选类型：MAP_TYPE_NORMAL,MAP_TYPE_SATELLITE,MAP_TYPE_NIGHT
                    aMap?.mapType = AMap.MAP_TYPE_NORMAL // 卫星地图模式
                    // 倾斜手势
                    aMap?.setInfoWindowAdapter(myMarkerInfoWindowAdapter)
                    // 点击地图隐藏信息弹窗
                    aMap?.setOnMapClickListener { myMarkerInfoWindowAdapter.currentMarker?.hideInfoWindow() }

                    aMap?.setOnMarkerClickListener {
                        // 如果没有和当前点击的点位置重复的点，就直接显示信息弹窗
                        for (i in 0 until markersWithSamePos.size) {
                            val markers = markersWithSamePos[i]

                            if (it.position.longitude == markers[0].position.longitude && it.position.latitude == markers[0].position.latitude) {
                                if (markers.size == 1) {
                                    // 如果没有和当前点击的点位置重复的点，就直接显示信息弹窗
                                    it.showInfoWindow()
                                    // 显示跳转导航的弹窗
                                    Log.e(
                                        this.toString(),
                                        "Page: ${settingViewModel.isShowNavigationDialog.value}"
                                    )
                                    if (settingViewModel.isShowNavigationDialog.value) {
                                        jumpToMapApplicationDialog(locationManager, it)
                                    }
                                } else {
                                    // 有和当前点击的点位置重复的点,显示一个弹窗选择一个点查看信息
                                    Toast.makeText(context, "有重复的点", Toast.LENGTH_SHORT).show()


                                    val titles: ArrayList<CharSequence> = arrayListOf()
                                    markers.forEach { marker ->
                                        titles.add(marker.title)
                                    }

                                    Log.e(
                                        this.toString(),
                                        "onCreateView: titles 的长度: ${titles.size}"
                                    )

                                    Log.e(this.toString(), "onCreateView: titles: $titles")


                                    // 显示一个弹窗显示重复重复的点


                                    var selected = 0

                                    AlertDialog.Builder(this@MapFragment.activity)
                                        .setTitle("设备位置重复，选择一个设备查看信息")
                                        .setSingleChoiceItems(
                                            titles.toTypedArray(), -1
                                        ) { _, which ->
                                            run {
                                                selected = which
                                            }
                                        }.setPositiveButton("确定") { dialog, _ ->
                                            run {
                                                val marker = markers[selected]
                                                // 显示选择的设备信息
                                                marker.showInfoWindow()
                                                // 判断是否要显示跳转到高德地图的弹窗
                                                if (settingViewModel.isShowNavigationDialog.value) {
                                                    jumpToMapApplicationDialog(
                                                        locationManager, it
                                                    )
                                                }
                                            }
                                        }.show()

                                }
                            }
                        }


                        // 责任链模式，我则一环结束
                        true
                    }
                    Log.e(this@MapFragment.toString(), "onCreateView: 地图初始好没好$aMap")
                    Log.e(
                        this@MapFragment.toString(), "onCreateView: 地图初始好没好${mapView.map}"
                    )
                    initObserver(aMap!!, myMarkerInfoWindowAdapter, mapViewModel)

                }
            }
        }
    }

    /**
     * 跳转到高德地图
     *
     * @param locationManager 定位管理器
     * @param it 高德地图的Marker
     */
    private fun jumpToMapApplicationDialog(
        locationManager: LocationManager?, it: Marker
    ) {
        AlertDialog.Builder(context).setMessage("是否跳转到高德地图导航")
            .setPositiveButton("确认") { _, _ ->
                run {
                    // 让高德地图来导航
                    val routePara = RoutePara()
                    with(routePara) {
                        val lastKnownLocation: Location? = if (ActivityCompat.checkSelfPermission(
                                requireContext(), Manifest.permission.ACCESS_FINE_LOCATION
                            ) == PackageManager.PERMISSION_GRANTED
                            &&
                            ActivityCompat.checkSelfPermission(
                                requireContext(),
                                Manifest.permission.ACCESS_COARSE_LOCATION
                            ) == PackageManager.PERMISSION_GRANTED
                        ) {
                            locationManager?.getLastKnownLocation(
                                LocationManager.GPS_PROVIDER
                            )
                        } else {

                            registerForActivityResult.launch(
                                arrayOf(
                                    Manifest.permission.ACCESS_FINE_LOCATION,
                                    Manifest.permission.ACCESS_COARSE_LOCATION
                                )
                            )
                            return@run
                        }

                        println(lastKnownLocation)

                        startPoint = if (lastKnownLocation != null) {
                            LatLng(
                                lastKnownLocation.latitude, lastKnownLocation.longitude
                            )
                        } else if (this@MapFragment::mAMapLocation.isInitialized) {
                            LatLng(
                                mAMapLocation.latitude, mAMapLocation.longitude
                            )
                        } else {
                            println("起始点位置初始化失败，不能导航")
                            Toast.makeText(
                                context,
                                "起始点位置初始化失败，不能导航,打开定位后再试",
                                Toast.LENGTH_LONG
                            ).show()
                            return@run
                        }
                        endPoint = it.position
                        startName = "我的位置"
                        endName = "设备位置"
                    }

                    AMapUtils.openAMapDrivingRoute(routePara, context)
                }
            }.setNegativeButton("返回") { dialogInterface, _ ->
                kotlin.run {
                    dialogInterface.dismiss()
                }
            }.show()
    }

    private fun initObserver(
        aMap: AMap, myMarkerInfoWindowAdapter: MyMarkerInfoWindowAdapter, mapViewModel: MapViewModel
    ) {

        // 不能倾斜手势
        aMap.uiSettings.isTiltGesturesEnabled = false
        // 不能旋转
        aMap.uiSettings.isRotateGesturesEnabled = false

        mapViewModel.loadState.observe(viewLifecycleOwner) {
            when (it) {
                LoadState.LOADING -> {
//                    dialog = ProgressDialog.show(context, "", "登录中", true)
                }

                LoadState.SUCCESS -> {
                    Log.e(this.toString(), "initObserver: 监听成功")
                }

                LoadState.EMPTY -> TODO()
                LoadState.ERROR -> {
                    Toast.makeText(context, "服务器错误，请联系管理员", Toast.LENGTH_LONG).show()
                }

                LoadState.FAIL -> TODO()

                null -> TODO()
            }
        }
        mapViewModel.tokenExpire.observe(viewLifecycleOwner) {
            if (it) {
                Toast.makeText(context, "登录过期，请重新登录", Toast.LENGTH_LONG).show()
                // 删除token
                val preferences = requireActivity().getSharedPreferences(
                    Constants.store_key,
                    Context.MODE_PRIVATE
                )
                with(preferences.edit()) {
                    remove("user")
                    clear()
                    apply()
                }
                startActivity(
                    Intent(
                        context, LoginActivity::class.java
                    ).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                )
                this.activity?.finish()
            }
        }
        mapViewModel.machineInfos.observe(viewLifecycleOwner) { machineItems ->
            Log.e(this.toString(), "initObserver: 观察到机械数据更新$aMap")
//            Toast.makeText(context, "设备数量:${machineItems.size}", Toast.LENGTH_LONG).show()

            myMarkerInfoWindowAdapter.setData(machineItems)
            println("获取点的信息成功")

            // 清空地图上的覆盖物
            aMap.clear()

            val markerOptionsArray: ArrayList<MarkerOptions> = arrayListOf()


            // 清空上一次的重复点信息
            markersWithSamePos.clear()

            // create maker
            machineItems.forEach { item ->
                val latLng = LatLng(
                    item.latitude?.toDouble() ?: return@forEach,
                    item.longitude?.toDouble() ?: return@forEach
                )
                val markerOptions =
                    MarkerOptions().position(latLng).snippet("DefaultMarker").title(item.mec_no)
                markerOptions.alpha
                when (item.status) {
                    0 -> {
                        // 静止的机器
//                        markerOptions.icon(BitmapDescriptorFactory.fromResource(R.mipmap.grey_site))
                        markerOptions.icon(
                            BitmapDescriptorFactory.defaultMarker(
                                BitmapDescriptorFactory.HUE_AZURE
                            )
                        )
                    }

                    1 -> {
                        // 工作的机器
                        markerOptions.icon(
                            BitmapDescriptorFactory.defaultMarker(
                                BitmapDescriptorFactory.HUE_GREEN
                            )
                        )
                    }


                    else -> {
                        markerOptions.icon(
                            BitmapDescriptorFactory.defaultMarker(
                                BitmapDescriptorFactory.HUE_YELLOW
                            )
                        )
                    }
                }

                markerOptionsArray.add(markerOptions)


            }

            //在地图上添一组图片标记（marker）对象，并设置都在当前地图可视区域范围内显示。。
            val markers = aMap.addMarkers(markerOptionsArray, true)

            markers.forEach {
                // 添加第一个点
                if (markersWithSamePos.size == 0) {
                    // 直接创建一个新的一维数组添加marker
                    val temp = arrayListOf<Marker>()
                    temp.add(it)
                    markersWithSamePos.add(temp)
                } else {
                    // 不是第一个点
                    for (i in 0 until markersWithSamePos.size) {
                        // 取出二维数组中的第一维
                        val markersWithSamePo = markersWithSamePos[i]
                        // 取出一维度数组的第一个
                        val marker1 = markersWithSamePo[0]

                        if (marker1.position.longitude == it.position.longitude && marker1.position.latitude == it.position.latitude) {
                            // 和这个数组的第一个元素位置相同，添加到这个数组的末尾
                            markersWithSamePo.add(it)

                            // TODO:有重复的点，旁边的lable只显示一个

                            // 找到位置了，就可以处理下一条数据了
                            break
                        } else if (i + 1 == markersWithSamePos.size) {
                            // 遍历完成都没有重复位置的点，直接创建一个新的一维数组添加marker
                            val temp: ArrayList<Marker> = arrayListOf()

                            temp.add(it)
                            markersWithSamePos.add(temp)

                            // 上面push导致长度 + 1，不能跳出循环
                            break
                        }
                    }
                }
            }
        }
    }

    override fun onResume() {
        super.onResume()
        mMapView?.onResume()
    }

    override fun onPause() {
        super.onPause()
        mMapView?.onPause()
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
        mMapView?.onDestroy()
    }
}